#ifndef REORDERING_H
#define REORDERING_H

#include <set>
#include <map>
#include "SharedArray.h"
#include "Column.h"
#include "AggregationData.h"

using namespace std;

namespace {

SharedArray<int> summedColumns(const SharedArray<Column>& in, const SharedArray<AggregationData>& aggregations, Type type) {
	SharedArray<int> cols(aggregations.size());
	set<int> colsSet;

	int curCol = 0;
	for (int i = 0; i < aggregations.size(); ++i) {
		const int col = aggregations[i].column;

		if (aggregations[i].type == AggregationData::SUM &&
				in[col].type() == type) {
			if (colsSet.find(col) == colsSet.end()) {
				cols[curCol++] = col;
				colsSet.insert(col);
			}
		}
	}

	cols.shrink(curCol);

	return cols;
}

bool areThereCountColumns(const SharedArray<AggregationData>& aggregations) {
	for (int i = 0; i < aggregations.size(); ++i)
		if (aggregations[i].type == AggregationData::COUNT)
			return true;

	return false;
}

int countColumnsCount(const SharedArray<AggregationData>& aggregations) {
	int counts = 0;

	for (int i = 0; i < aggregations.size(); ++i)
		if (aggregations[i].type == AggregationData::COUNT)
			++counts;

	return counts;
}

SharedArray<int> outValueColumns(const SharedArray<Column>& in, const SharedArray<AggregationData>& aggregations) {
	SharedArray<int> columns(aggregations.size());
	map<int, int> sumMapping;

	int curColInt = 0;
	int curColDouble = 0;
	for (int i = 0; i < aggregations.size(); ++i) {
		if (aggregations[i].type == AggregationData::SUM) {
			const int col = aggregations[i].column;
			if (sumMapping.find(col) == sumMapping.end()) {
				if (in[col].type() == INT) {
					sumMapping[col] = curColInt++;
				} else {
					assert(in[col].type() == DOUBLE);
					sumMapping[col] = curColDouble++;
				}
			}
		} else {
			assert(aggregations[i].type == AggregationData::COUNT);
		}
	}

	const int countColumn = curColInt + curColDouble;

	for (int i = 0; i < aggregations.size(); ++i) {
		if (aggregations[i].type == AggregationData::SUM) {
			const int col = aggregations[i].column;
			if (in[col].type() == DOUBLE) {
				columns[i] = sumMapping[col];
			} else {
				assert(in[col].type() == INT);
				columns[i] = curColDouble + sumMapping[col];
			}
		} else {
			assert(aggregations[i].type == AggregationData::COUNT);
			columns[i] = countColumn;
		}
	}
	
	return columns;
}

}

#endif
